package top.vanchor.myblog2back.controller.user;


import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import top.vanchor.myblog2back.config.JwtConfigProperties;
import top.vanchor.myblog2back.entity.BlogUser;
import top.vanchor.myblog2back.service.IBlogSubscribeService;
import top.vanchor.myblog2back.service.IBlogUserService;
import top.vanchor.myblog2back.utils.ImageUtil;
import top.vanchor.myblog2back.utils.JWTUtils;
import top.vanchor.myblog2back.utils.JwtInterceptor;
import top.vanchor.myblog2back.utils.SMSUtil;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.sql.Date;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author Ding
 * @since 2021-11-12
 */
@CrossOrigin
@RestController
@RequestMapping("/blogUser")
public class BlogUserController {

    @Value("${uploadPath}")
    private String upLoadPath;

    @Value("${server.port}")
    private String port;

    @Value("${ipHost}")
    private String ipHost;

    @Autowired
    private JwtConfigProperties jwtConfigProperties;

    @Resource
    IBlogUserService iBlogUserService;

    @Resource
    IBlogSubscribeService blogSubscribeService;

    @PostMapping("/login")
    @ResponseBody
    public JSONObject login(@RequestBody JSONObject data){
        String username = String.valueOf(data.get("username"));
        String password = String.valueOf(data.get("password"));
        BlogUser blogUser = iBlogUserService.toLogin(username,password);
        JSONObject jsonObject = new JSONObject();
        JSONObject jsonDemo = new JSONObject();
        if (blogUser!=null){
            if(blogUser.getUStatus().equals("1")){
                // 登录成功，返回token
                jsonObject.put("code", 200);
                jsonObject.put("msg","登录成功！");
                jsonDemo.put("userInfo",blogUser);
                jsonDemo.put("token", JWTUtils.sign(String.valueOf(blogUser.getUId()),jwtConfigProperties));
                jsonObject.put("data",jsonDemo);
            }else{
                jsonObject.put("code", 250);
                jsonObject.put("msg","账号已被封禁");
            }
        }else{
            jsonObject.put("code", 500);
            jsonObject.put("msg","手机号或密码错误");
        }
        return jsonObject;
    }

    @ApiOperation("查询用户by查询者id和目标id")
    @PostMapping("/getUserInfoById")
    @ResponseBody
    public JSONObject getUserInfoById(@RequestBody JSONObject data){
        Integer uId = Integer.valueOf(String.valueOf(data.get("uId")));
        Integer loginUserId = Integer.valueOf(String.valueOf(data.get("loginUserId")));
        BlogUser blogUser = iBlogUserService.getUserInfoById(uId,loginUserId);
        JSONObject jsonObject = new JSONObject();
        JSONObject jsonDemo = new JSONObject();
        if (blogUser!=null){
            // 登录成功，返回token
            jsonObject.put("code", 200);
            jsonObject.put("msg","ok");
            jsonDemo.put("userInfo",blogUser);
            jsonObject.put("data",jsonDemo);
        }else{
            jsonObject.put("code", 500);
            jsonObject.put("msg","无法查询到该用户信息");
        }
        return jsonObject;
    }

    /**
     * 修改用户信息
     * @param dt form表单
     * @return JSONObject 新的user对象
     */
    @RequestMapping("/toUpdateUserInfo")
    @ResponseBody
    @ApiOperation("修改用户信息")
    public JSONObject toModifyUserInfo(@RequestBody JSONObject dt){
        JSONObject jsonObject = new JSONObject();
        JSONObject data = dt.getJSONObject("form");
        //向bean存值
        BlogUser blogUser = new BlogUser();
        blogUser.setUId(Integer.parseInt(String.valueOf(data.get("uId"))));
        blogUser.setUName(String.valueOf(data.get("uName")));
        blogUser.setUBirthday(new Date(Long.valueOf(String.valueOf(data.get("uBirth")))));
        blogUser.setUSex(Integer.parseInt(String.valueOf(data.get("uSex"))));
        if (iBlogUserService.toModifyUserInfo(blogUser) >= 0){
            jsonObject.put("code",200);
            jsonObject.put("msg","操作成功");
            JSONObject jsonObject1 = new JSONObject();
            jsonObject1.put("user",iBlogUserService.getUserById(blogUser.getUId()));
            jsonObject.put("data",jsonObject1);
        }else{
            jsonObject.put("code",500);
            jsonObject.put("msg","服务器异常，操作失败");
        }
        return jsonObject;
    }

    /**
     * 修改用户头像
     * @param data JsonObject对象
     * @return JSONObject 新的user对象
     */
    @RequestMapping("/updateAvatar")
    @ResponseBody
    @ApiOperation("修改用户头像")
    public JSONObject updateAvatar(@RequestBody JSONObject data){
        JSONObject jsonObject = new JSONObject();
        String url = String.valueOf(data.get("url"));
        Integer uId = Integer.valueOf(String.valueOf(data.get("uId")));
        //向bean存值
        BlogUser blogUser = new BlogUser();
        blogUser.setUId(uId);
        blogUser.setUAvatar(url);
        if (iBlogUserService.toModifyUserInfo(blogUser) >= 0){
            jsonObject.put("code",200);
            jsonObject.put("msg","操作成功");
            JSONObject jsonObject1 = new JSONObject();
            jsonObject1.put("user",iBlogUserService.getUserById(blogUser.getUId()));
            jsonObject.put("data",jsonObject1);
        }else{
            jsonObject.put("code",500);
            jsonObject.put("msg","服务器异常，操作失败");
        }
        return jsonObject;
    }

    /**
     * 修改用户头像
     * @param data JsonObject对象
     * @return JSONObject 新的user对象
     */
    @RequestMapping("/sendShortSMS")
    @ResponseBody
    @ApiOperation("发送验证码短信")
    public JSONObject sendShortSMS(@RequestBody JSONObject data) throws ClientException {
        JSONObject jsonObject = new JSONObject();
        JSONObject jsonDemo = new JSONObject();
        String code = Integer.toString((int)(Math.random()*9999)+100);
        String phone = String.valueOf(data.get("username"));
        if (!iBlogUserService.isPhoneNumUnique(String.valueOf(data.get("username")))){
            jsonObject.put("code", 400);
            jsonObject.put("msg", "该手机号码已被注册");
        }else{
            //发送验证码
            String strCode = SMSUtil.toEncode(code, phone);
            SendSmsResponse response = SMSUtil.sendSms(phone,code);
            if (response.getCode().equals("OK")){
                jsonObject.put("code",200);
                jsonObject.put("msg","验证码发送成功，5分钟内有效");
                jsonDemo.put("checkcode",strCode);
                jsonObject.put("data",jsonDemo);
            }else{
                jsonObject.put("code",500);
                jsonObject.put("msg","验证码发送失败！");
            }
        }
        return jsonObject;
    }

    /**
     * 用户注册
     * @param data 注册数据
     * @return JSONObject 注册状态
     */
    @RequestMapping("/register")
    @ApiOperation("用户注册")
    @ResponseBody
    public JSONObject userRegister(@RequestBody Map<String, Object> data){
        JSONObject jsonObject = new JSONObject();
        if (data.get("confirmCode") == "" || data.get("confirmCode") == null){
            jsonObject.put("code",420);
            jsonObject.put("msg", "验证码无效！请尝试获取");
            return jsonObject;
        }
        JSONObject j1 = SMSUtil.toDecode(String.valueOf(data.get("confirmCode")));
        if (Integer.parseInt(String.valueOf(j1.get("code"))) == 300){
            //验证码过期
            jsonObject.put("code",450);
            jsonObject.put("msg", "验证码已过期，请重新获取！");
        }else{
            if (!String.valueOf(data.get("phoneNum")).equals(String.valueOf(j1.get("phoneNum"))) || !String.valueOf(data.get("checkCode")).equals(String.valueOf(j1.get("checkcode")))){
                //验证码错误或与手机号码不匹配
                jsonObject.put("code",480);
                jsonObject.put("msg", "验证码有误，请核对！");
            }else{
                if (!iBlogUserService.isPhoneNumUnique(String.valueOf(data.get("phoneNum")))){
                    jsonObject.put("code", 400);
                    jsonObject.put("msg", "该手机号码已被注册");
                }else{
                    if(iBlogUserService.userRegister(data) > 0){
                        jsonObject.put("code", 200);
                        jsonObject.put("msg", "注册成功！请前往登录");
                    }else{
                        jsonObject.put("code", 0);
                        jsonObject.put("msg", "操作失败");
                    }
                }
            }
        }

        return jsonObject;
    }



    /**
     * 上传用户头像
     * @param file 图片
     * @return JSONObject 新的user对象
     */
    @RequestMapping("/toUploadImg")
    @ApiOperation("上传图片免压缩")
    @ResponseBody
    public JSONObject toUploadImg(@RequestParam MultipartFile file) throws UnsupportedEncodingException {
        JSONObject jsonObject = new JSONObject();
        //文件夹不存在--创建文件夹
        File file1 = new File(upLoadPath);
        if (!file1.exists()) {
            file1.mkdirs();
        }
        //创建随机文件名
        String filename = UUID.randomUUID().toString().replaceAll("-", "");
        //文件后缀
        String ext = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        //新文件名
        String newFileName = filename+ext;
        //新文件全路径
        String url = upLoadPath+newFileName;
        //服务器全称
        String allUrl = ipHost+":"+port+"/"+newFileName;
        try {
            file.transferTo(new File(url));
        } catch (IOException e) {
            e.printStackTrace();
        }
        jsonObject.put("stat",200);
        jsonObject.put("url",allUrl);
        return jsonObject;
    }

    /**
     * 上传用户头像
     * @param file 图片
     * @return JSONObject 新的user对象
     */
    @RequestMapping("/toUploadAvatar")
    @ApiOperation("上传压缩图片")
    @ResponseBody
    public JSONObject uploadFile(@RequestParam MultipartFile file,
                                 HttpServletRequest request,
                                 HttpServletResponse response) throws IOException {
        response.setCharacterEncoding("utf-8");
        request.setCharacterEncoding("utf-8");
        JSONObject jsonObject = new JSONObject();
        //文件上传的目标文件夹不存在--创建文件夹
        File file1 = new File(upLoadPath);
        if (!file1.exists()) {
            file1.mkdirs();
        }
        //创建随机文件名
        String filename = UUID.randomUUID().toString().replaceAll("-", "");
        //获取文件后缀
        String ext1 = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        String ext = ext1.substring(1);
        //组合的不重复新文件名
        String newFileName = filename+"."+ext;
        //新文件全路径--用于上传并存储
        String url = upLoadPath+newFileName;
        //服务器全称--用于存到服务器
        String allUrl = ipHost+":"+port+"/"+newFileName;
        //-----------------------------------------------------------------------------
        //目标文件夹
        String target = url;
        //new文件对象
        File targetFile = new File(target);
        //将multipartFile文件转成byte数组----------------------------↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        //让数组的长度是文件大小，并且多给16字节
        Integer byteLongs = Math.toIntExact(file.getSize() + 16);
        byte[] buff = new byte[byteLongs];
        int rc = 0;
        while ((rc = file.getInputStream().read(buff, 0, buff.length)) > 0) {
            swapStream.write(buff, 0, rc);
            System.out.println(rc);
            if (file.getSize()==rc){
                break;
            }
        }
        //转为byte[]成功---------------------------------------------↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
        //预进行流处理
        ByteArrayInputStream is = new ByteArrayInputStream(swapStream.toByteArray());
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            //流处理过程--输入、输出流、宽、高、尾缀
            ImageUtil.zoomImage(is,os,100,100,ext);
            ImageUtil.writeFile(os,targetFile);
        } catch (Exception e) {
            System.err.println("ERROR_LOG__InputStream:"+is);
            System.err.println("ERROR_LOG__OutputStream:"+os);
            System.err.println("ERROR_LOG__Ext:"+ext);
            jsonObject.put("stat",500);
            e.printStackTrace();
            return jsonObject;
        }
        //以上没有出现异常，就成功
        jsonObject.put("stat",200);
        jsonObject.put("url",allUrl);
        return jsonObject;
    }


    @RequestMapping("/toStarUser")
    @ResponseBody
    @ApiOperation("关注用户")
    public JSONObject toStarUser(@RequestBody JSONObject data){
        JSONObject jsonObject = new JSONObject();
        //发起关注者id
        Integer handleId = Integer.parseInt(String.valueOf(data.get("handleId")));
        //被关注者id
        Integer targetId = Integer.parseInt(String.valueOf(data.get("targetId")));

        Integer isStar = blogSubscribeService.toStarUser(handleId,targetId);

        if (isStar > 0){
            jsonObject.put("code",200);
            jsonObject.put("msg","关注成功");
        }else{
            jsonObject.put("code",500);
            jsonObject.put("msg","服务器异常，操作失败");
        }

        return jsonObject;
    }

    @RequestMapping("/toUnStarUser")
    @ResponseBody
    @ApiOperation("取关用户")
    public JSONObject toUnStarUser(@RequestBody JSONObject data){
        JSONObject jsonObject = new JSONObject();
        //发起关注者id
        Integer handleId = Integer.parseInt(String.valueOf(data.get("handleId")));
        //被关注者id
        Integer targetId = Integer.parseInt(String.valueOf(data.get("targetId")));

        Integer isStar = blogSubscribeService.toUnStarUser(handleId,targetId);

        if (isStar > 0){
            jsonObject.put("code",200);
            jsonObject.put("msg","取关成功");
        }else{
            jsonObject.put("code",500);
            jsonObject.put("msg","服务器异常，操作失败");
        }

        return jsonObject;
    }

    @RequestMapping("/getFriendList")
    @ResponseBody
    @ApiOperation("获取好友列表")
    public JSONObject getFriendList(){
        JSONObject jsonObject = new JSONObject();
        //当前用户id
        Integer id = Integer.valueOf(JWTUtils.getUserId(JwtInterceptor.getTokenInfo()));

        List<BlogUser> friends = new ArrayList<>();
        try {
            friends = iBlogUserService.getFriendListById(id);
            jsonObject.put("code",200);
            jsonObject.put("msg","获取成功");
            JSONObject jsonTemp = new JSONObject();
            jsonTemp.put("friends",friends);
            jsonObject.put("data",jsonTemp);
        }catch (Exception e){
            e.printStackTrace();
            jsonObject.put("code",500);
            jsonObject.put("msg","服务器异常，操作失败");
        }
        return jsonObject;
    }

    /**
     * 无需token
     * @return
     */
    @RequestMapping("/searchUsers")
    @ResponseBody
    @ApiOperation("以用户的身份-搜索用户")
    public JSONObject searchUsers(@RequestBody JSONObject data){
        JSONObject jsonObject = new JSONObject();
        String searchText = String.valueOf(data.get("searchText"));
        if (searchText.equals("")){
            jsonObject.put("code",500);
            jsonObject.put("msg","不允许搜索空内容");
        }
        //登录就传登录id，辨识他与列表中用户的关系
        Integer id = Integer.valueOf(String.valueOf(data.get("userId")));
        //页码
        Integer index = Integer.valueOf(String.valueOf(data.get("index")));
        PageInfo<BlogUser> users = new PageInfo<>();
        try {
            users = iBlogUserService.searchUsers(searchText,id,index,5);
            jsonObject.put("code",200);
            jsonObject.put("msg","获取成功");
            JSONObject jsonTemp = new JSONObject();
            jsonTemp.put("users",users.getList());
            jsonTemp.put("total",users.getTotal());
            jsonTemp.put("pages",users.getPages());
            jsonObject.put("data",jsonTemp);
        }catch (Exception e){
            e.printStackTrace();
            jsonObject.put("code",500);
            jsonObject.put("msg","服务器异常，操作失败");
        }
        return jsonObject;
    }
}
